/**
 *
 */
package org.cmcc.pcap.jpcap.tcp;

import java.util.ArrayList;
import java.util.HashMap;


import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.cmcc.pcap.jpcap.capture.HandlerManager;
import org.cmcc.pcap.jpcap.tcp.http.HttpHandler;
import org.cmcc.pcap.jpcap.tcp.https.HttpsHandler;
import org.cmcc.pcap.jpcap.tcp.tcp.TcpHandler;

/**
 * @Date 2018年1月16日 下午7:45:07
 * @author Amish
 *
 */
public class TcpProtocolDispatcher implements Runnable{
	private static Logger logger = LogManager.getLogger(TcpProtocolDispatcher.class);
    boolean flag = true;//忘了干啥用的了....
    TcpConnectionCache tcpConnectionCache;
    
    private HashMap<String, TcpProtocolHandler> hashmap;
    private String taskId;
    
    public String getTaskId() {
		return taskId;
	}

	public void setTaskId(String taskId) {
		this.taskId = taskId;
	}

	public TcpProtocolDispatcher( TcpConnectionCache tcpConnectionCache){
    	this.tcpConnectionCache = tcpConnectionCache;
    	this.hashmap = new HashMap<>();
    }
    
    /**
     * 用于识别TCP的应用层协议，并返回对应的Handler
     * @return
     */
    private TcpProtocolHandler distinguishTcpProtocol(TcpConnection tcpConnection){
    	//根据TcpProtocolFilter的结果，直接判断TcpConnection中的对应成员变量
    	switch(tcpConnection.protocol){
    	case HTTP:{
    		if(hashmap.containsKey("HTTP")) {
    			return hashmap.get("HTTP");
    		}
    		else {
				try {
					hashmap.put("HTTP", (TcpProtocolHandler) HandlerManager.getHandler("http"));
				} catch (IllegalAccessException | InstantiationException e) {
					logger.error(e.getMessage());
				}
				return hashmap.get("HTTP");
    		}
//    	    return new HttpHandler();
    	}


    	case HTTPS:{
    		if(hashmap.containsKey("HTTPS")) {
    			return hashmap.get("HTTPS");
    		}
    		else {
				try {
					hashmap.put("HTTP", (TcpProtocolHandler) HandlerManager.getHandler("https"));
				} catch (IllegalAccessException | InstantiationException e) {
					logger.error(e.getMessage());
				}
    			return hashmap.get("HTTPS");
    		}
    	}
    	
    	case TCP:{
    		logger.debug("this is return tcp handler !");
    		if(hashmap.containsKey("TCP")) {
    			return hashmap.get("TCP");
    		}
    		else {
				try {
					hashmap.put("HTTP", (TcpProtocolHandler) HandlerManager.getHandler("tcp"));
				} catch (IllegalAccessException | InstantiationException e) {
					logger.error(e.getMessage());
				}
    			return hashmap.get("TCP");
    		}
    	}

    	default:
    		//return new DefaultProtocolHandler();
    		logger.info("Can not dispatcher protocol : "+tcpConnection.protocol.name() + " with first seq num : " +tcpConnection.al.get(0).tcpPacket.sequence);
    		return null;
    	}
    }
    
	@Override
	public void run() {
		
		while(this.flag){
			ArrayList<TcpConnection>  al  = tcpConnectionCache.getTcpConnection();//此处由于同步 可能阻塞
			//int totalHandledPacketNum = 0; 
			for(TcpConnection tcpConnection : al){
				int handledPacketNum = tcpConnection.al.size();//提前获取需要处理的Packet数量，TOFIX何时清零的？
				try {
					TcpProtocolHandler tcpProtocolHandler = distinguishTcpProtocol(tcpConnection);
					if(tcpProtocolHandler != null){
						tcpProtocolHandler.handle(tcpConnection,taskId);
					}else{
						//logger.error("Can not the protocol handler");
					}
				}catch(Exception e) { 
					logger.error(e.getCause(),e);	
				}
				finally {
					//totalHandledPacketNum += handledPacketNum;
					tcpConnectionCache.handledPacketNum.getAndAdd(handledPacketNum);//记录已经处理的Packet数量
				}
				
			}
			
			//TODO TOFIX lvpin 20180619 如果写库操作放在这里，应该在写库操作完成后，使用totalHandledPacketNum来计数，否则可能导致提前结束处理
			
		}
	}
	
	public void terminate() {
		this.flag = false;
	}
	
	

}
